package com.gxnzd.communityelderly.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxnzd.communityelderly.commom.R;
import com.gxnzd.communityelderly.dao.*;
import com.gxnzd.communityelderly.entity.Community;
import com.gxnzd.communityelderly.entity.Employee;
import com.gxnzd.communityelderly.entity.Forum;
import com.gxnzd.communityelderly.entity.Reservation;
import com.gxnzd.communityelderly.mapper.CommunityMapper;
import com.gxnzd.communityelderly.mapper.EmployeeMapper;
import com.gxnzd.communityelderly.mapper.ForumMapper;
import com.gxnzd.communityelderly.service.ReservationService;
import com.gxnzd.communityelderly.mapper.ReservationMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
* @author 23234
* @description 针对表【reservation】的数据库操作Service实现
* @createDate 2024-10-31 15:23:13
*/
@Service
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation>
    implements ReservationService{

    @Resource
    private ReservationMapper reservationMapper;

    @Resource
    private EmployeeMapper employeeMapper;

    @Resource
    private CommunityMapper communityMapper;

    @Resource
    private ForumMapper forumMapper;

    @Resource
    private RedisTemplate redisTemplate;
    /**
     * 添加预约
     * @param reservation
     * @return
     */
    @Override
    public R addDegister(Reservation reservation) {
        LambdaQueryWrapper<Employee> userWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Employee> doctorWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(Employee::getEmpId,reservation.getUserId());
        doctorWrapper.eq(Employee::getEmpId,reservation.getDoctorId());
        Employee user = employeeMapper.selectOne(userWrapper);
        Employee doctor = employeeMapper.selectOne(doctorWrapper);
        if(user == null){
            return R.error("没有此用户");
        }
        if(doctor == null){
            return R.error("没有此医生");
        }
        //对预约状态进行初始化
        reservation.setStatus("1");
        //判断此用户预约日期 表里是否重复
        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getUserId,reservation.getUserId())
                .eq(Reservation::getAppointmentDate, reservation.getAppointmentDate())
                .eq(Reservation::getAppointmentTime,reservation.getAppointmentTime());
        Reservation one = reservationMapper.selectOne(wrapper);
        if(one != null){
            return R.error("此用户已经预约了");
        }
        //添加
        reservationMapper.insert(reservation);
        return R.success("添加成功");
    }

    /**
     * 根据用户id获取预约记录
     * @param empId
     * @return
     */
    @Override
    public R getByIdList(Long empId,String type,Integer page, Integer pageSize,String status) {
        ArrayList<RegisterInfo> list = new ArrayList<>();
        LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Employee::getEmpId,empId);
        Employee employee = employeeMapper.selectOne(wrapper);
        if (employee == null){
            return R.error("没有此用户");
        }

        LambdaQueryWrapper<Reservation> queryWrapper = new LambdaQueryWrapper<>();
        List<Reservation> reservationList = new ArrayList<Reservation>();

        if("2".equals(type)){
            Page<RegisterInfo> registerInfoPage = new Page<>(page,pageSize);
            //是用户
            Page<Reservation> reservationPage = new Page<>(page,pageSize);
//            查询分页
            IPage<Reservation> selectPage = reservationMapper.selectUserPageInfo(empId, status, reservationPage);
            for (Reservation reservation:selectPage.getRecords()) {
                //判断一下是否过期了
                reservation = isExpireStauts(reservation);
                LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(Employee::getEmpId,reservation.getDoctorId());
                Employee doctor = employeeMapper.selectOne(lambdaQueryWrapper);
                RegisterInfo info = new RegisterInfo();
                info.setEmployee(doctor);
                info.setReservation(reservation);
                list.add(info);
            }
            registerInfoPage.setRecords(list);
            registerInfoPage.setPages(selectPage.getPages());
            reservationPage.setSize(selectPage.getSize());
            reservationPage.setTotal(selectPage.getTotal());
            reservationPage.setCurrent(selectPage.getCurrent());
            return R.success(registerInfoPage);
        }else{
            //是医生
            //获取当天的年月日
            LocalDate currentDate = LocalDate.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String formattedDate = currentDate.format(formatter);
            //判断当前时间是否是上午 返回值0 表示上午 返回值 1 表示下午
            GregorianCalendar cg = new GregorianCalendar();
            int isMorning = cg.get(GregorianCalendar.AM_PM);
            String appTime = new String("");
            if(isMorning == 0){
                appTime = "morning";
            }else{
                appTime = "afternoon";
            }
            //条件构造
            queryWrapper.eq(Reservation::getDoctorId,empId)
                    .eq(Reservation::getStatus,"1")
                    .eq(Reservation::getAppointmentDate,formattedDate)
                    .eq(Reservation::getAppointmentTime,appTime);
            reservationList = reservationMapper.selectList(queryWrapper);
            for (Reservation reservation:reservationList) {
                //判断一下是否过期了
                reservation = isExpireStauts(reservation);
                LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(Employee::getEmpId,reservation.getUserId());
                Employee user = employeeMapper.selectOne(lambdaQueryWrapper);
                RegisterInfo info = new RegisterInfo();
                info.setEmployee(user);
                info.setReservation(reservation);
                list.add(info);
            }
            return R.success(list);
        }


    }

    /**
     * 分页获取
     * @param page
     * @param pageSize
     * @param userId
     * @param doctorId
     * @return
     */
    @Override
    public R getPageListInfo(Integer page,
                             Integer pageSize,
                             Integer userId,
                             Integer doctorId,
                             String status,
                             String startDate,
                             String endDate) {
        Page<Reservation> pageInfo = new Page<>(page,pageSize);
        //获取分页
        IPage<Reservation> list = reservationMapper.selectPageInfoList(userId, doctorId,status, pageInfo,startDate,endDate);
        Page<ReservationPageList> reservationPageListPage = new Page<>();
        //最终需要返回的数组数据
        ArrayList<ReservationPageList> reservationPageListArrayList = new ArrayList<>();
        List<Reservation> records = list.getRecords();
        for (Reservation reservation:records) {
            reservation = isExpireStauts(reservation);
            ReservationPageList reservationPageInfo = new ReservationPageList();
            //查询用户信息
            LambdaQueryWrapper<Employee> userWrapper = new LambdaQueryWrapper<>();
            userWrapper.eq(Employee::getEmpId,reservation.getUserId());
            Employee userInfo = employeeMapper.selectOne(userWrapper);
            //判断用户是否还存在
            if(userInfo == null){
                //删除此预约记录
                reservationMapper.deleteById(reservation.getReservationId());
                continue;
            }
            reservationPageInfo.setUserId(userInfo.getEmpId());
            reservationPageInfo.setUserName(userInfo.getName());
            reservationPageInfo.setUserPhone(userInfo.getPhone());
            //查询医生信息
            LambdaQueryWrapper<Employee> doctorWrapper = new LambdaQueryWrapper<>();
            doctorWrapper.eq(Employee::getEmpId,reservation.getDoctorId());
            Employee doctorInfo = employeeMapper.selectOne(doctorWrapper);
            //判断医生是否存在
            if(doctorInfo == null){
                //删除此预约记录
                reservationMapper.deleteById(reservation.getReservationId());
                continue;
            }
            reservationPageInfo.setDoctorId(doctorInfo.getEmpId());
            reservationPageInfo.setDoctorName(doctorInfo.getName());
            reservationPageInfo.setDoctorPhone(doctorInfo.getPhone());

            //获取社区信息
            Community community = communityMapper.selectById(userInfo.getCommunityId());
            //判断社区是否存在
            if(community == null){
                //删除此预约记录
                reservationMapper.deleteById(reservation.getReservationId());
                continue;
            }
            reservationPageInfo.setCommunityId(community.getCommunityId());
            reservationPageInfo.setCommunityName(community.getCommunityName());
            //预约信息自己的数据
            reservationPageInfo.setReservationId(reservation.getReservationId());
            reservationPageInfo.setStatus(reservation.getStatus());
            reservationPageInfo.setAppointmentDate(reservation.getAppointmentDate());
            reservationPageInfo.setAppointmentTime(reservation.getAppointmentTime());
            //对数据进行追加
            reservationPageListArrayList.add(reservationPageInfo);
        }
        //对最后要返回的分页器进行设置
        reservationPageListPage.setPages(list.getPages());
        reservationPageListPage.setTotal(list.getTotal());
        reservationPageListPage.setCurrent(list.getCurrent());
        reservationPageListPage.setRecords(reservationPageListArrayList);
        reservationPageListPage.setSize(list.getSize());

        return R.success(reservationPageListPage);
    }

    //判断预约状态没有就诊就过期
    private Reservation isExpireStauts(Reservation reservation){
        if (reservation.getStatus().equals("3")){
            return reservation;
        }
        //当天0点的毫秒数
        long appTime = reservation.getAppointmentDate().getTime();
        //现在的时间
        long nowTime = new Date().getTime();
        if (reservation.getAppointmentTime().equals("morning")){
            appTime = appTime + 43200000L;
        }else{
            //正常下午下班时间为18点
//            appTime = appTime + 64800000L;
            //为了方便演示 将下午下班时间调到了22点
            appTime = appTime + 79200000L;
        }
        //如果预约时间超过了当天值班的时间就 预约过期
        if (nowTime >= appTime && reservation.getStatus().equals("1")){
            reservation.setStatus("3");
            reservationMapper.updateById(reservation);
            Reservation select = reservationMapper.selectById(reservation.getReservationId());
            return select;
        }
        //没有超过就直接返回
        return reservation;
    }

    /**
     * 过号
     * @param id
     * @return
     */
    @Override
    public R overNumberID(Long id) {
        Reservation reservation = reservationMapper.selectById(id);
        reservation.setStatus("3");
        reservationMapper.updateById(reservation);
        return R.success("成功过号");
    }


    /**
     * 获取过去七天的数据
     * @return
     */
    @Override
    public R getSevenDaysNum() {
//        ResStatistics savaDayNum = (ResStatistics) redisTemplate.opsForValue().get("savaDayNum");
//        if(savaDayNum != null){
//            return R.success(savaDayNum);
//        }
        //获取今日的毫秒数
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime startOfDay = LocalDateTime.now(zoneId).withHour(0).withMinute(0).withSecond(0).withNano(0);
        ZonedDateTime zonedDateTime = startOfDay.atZone(zoneId);
        long startOfDayMillis = zonedDateTime.toEpochSecond() * 1000; // ZonedDateTime的toEpochMilli()方法在Java 9及以上版本中可用
        //一天24小时的毫秒数
        long dayMilliseconds = 86400000;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        ArrayList<SevenDayReservationNum> numArrayList = new ArrayList<>();
        ArrayList<ResForumNum> forumNums = new ArrayList<>();
        //循环获取七天的数据
        for (int i = 1; i <= 7; i++) {
            //得到过去七天的日期
            Instant instant = Instant.ofEpochMilli(startOfDayMillis - (dayMilliseconds*i));
            // 使用系统默认时区将Instant转换为LocalDateTime
            LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
            // 使用formatter来格式化LocalDateTime对象
            String formattedDate = dateTime.format(formatter);
            //预约数量
            LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Reservation::getAppointmentDate,formattedDate);
            List<Reservation> list = reservationMapper.selectList(wrapper);
            SevenDayReservationNum reservationNum = new SevenDayReservationNum();
            reservationNum.setAppointmentDate(formattedDate);
            reservationNum.setNumber(list.size());
            numArrayList.add(reservationNum);
            //发帖数量
            //获取大前天的时间进行限制
            Instant frontDayTime = null;
            if(i == 1){
                frontDayTime = Instant.ofEpochMilli(startOfDayMillis);
            }else{
                frontDayTime =  Instant.ofEpochMilli(startOfDayMillis - (dayMilliseconds*(i-1)));
            }

            // 使用系统默认时区将Instant转换为LocalDateTime
            LocalDateTime frontTime = LocalDateTime.ofInstant(frontDayTime, ZoneId.systemDefault());
            //今一天的时间
            String frontDate = frontTime.format(formatter);
            LambdaQueryWrapper<Forum> queryWrapper = new LambdaQueryWrapper<>();
              queryWrapper .ge(Forum::getCreateTime,formattedDate)
                      .lt(Forum::getCreateTime,frontDate);
            List<Forum> forums = forumMapper.selectList(queryWrapper);
            ResForumNum forumNum = new ResForumNum();
            forumNum.setNumber(forums.size());
            forumNum.setDataString(formattedDate);
            forumNums.add(forumNum);
        }
        ResStatistics statistics = new ResStatistics();
        statistics.setSevenDay(numArrayList);
        statistics.setForumNums(forumNums);
//        redisTemplate.opsForValue().set("savaDayNum",statistics,24, TimeUnit.HOURS);
        return R.success(statistics);
    }
}




